<?php
/**
 * @author Eugenio Fage
 * inspired by meneame
 */
class BanComponent extends Object{
	static $banModel=null;
	var $user_ip=null;
	var $user_proxy=null;
		
	function initialize($controller, $settings = array()) {
		if(!BanComponent::$banModel) BanComponent::$banModel=ClassRegistry::init('Ban');	

		// prepare Behavior only if it needs 
		if(!$this->user_ip){
			$not_proxy=$_SERVER['REMOTE_ADDR'] != getenv('SERVER_ADDR');
			$this->user_ip = $not_proxy ? $_SERVER['REMOTE_ADDR'] : getenv('HTTP_X_FORWARDED_FOR');
			$this->user_proxy =$not_proxy ? null : $_SERVER['REMOTE_ADDR'];
		}
				
		if(!self::$banModel) self::$banModel = ClassRegistry::init('Ban');
	}
			
	function getUserIp(){
		return $this->user_ip;
	}
	
	function getUserProxy(){
		return $this->user_proxy;
	}
	

	function notBannedProxy($proxy=null){
		$proxy=($proxy)? $proxy:$this->user_proxy;
		
		if(!$proxy) return true;
		
		return !BanComponent::$banModel->hasAny(array(
			'type'=>'proxy',
			'value'=>$this->subclasses_list($proxy),
			'OR'=>array(
				'expire'=>null,
				'expire > date_sub(now(), interval 1 minute)'
			)
		));
				 
	}
	
	function notBannedIp($ip=null,$check_subclass=false){
		if(!($ip=($ip) ? $ip:$this->user_ip)) return true;
			
		return !BanComponent::$banModel->hasAny(array(
			'type'=>'ip',
			'value'=>(!$check_subclass)?$ip: $this->subclasses_list($ip),
			'OR'=>array(
				'expire'=>null,
				'expire > date_sub(now(), interval 1 minute)'
			)
		));
				 
	}
	
	function notBannedEmail($email,$checkType=null){
		$email=strtolower($email);
		$conditions=array('type'=>'email','value'=>$email);
		
		if($checkType && strpos($email,'@')){
			$m=explode('@',$email);
						
			if($checkType=='mailbox') $conditions['value']=$m[0];
			if($checkType=='domain') $conditions['value']=$m[1];
		}
		
		return !BanComponent::$banModel->hasAny($conditions);
	}
					
	function notBannedHostname($hostname,$deep=true,$first_level=false){
			
		return !BanComponent::$banModel->hasAny(array(
			'type'=>'hostname',
			'value'=>(!$deep)?$hostname : $this->subdomains_list($hostname,$first_level),
			'OR'=>array(
				'expire'=>null,
				'expire > date_sub(now(), interval 1 minute)'
			)
		));	
	}
		
	function notBannedWord($words){
		$words=' '.strtolower($words);
		
		App::import('Sanitize');
		
		return !BanComponent::$banModel->hasAny(array(
			'type'=>'words',
			'INSTR( \' '.Sanitize::escape($words).'\', value ) >0',
			'OR'=>array(
				'expire'=>null,
				'expire > date_sub(now(), interval 1 minute)'
			)
		));
	}
	
	
	//TODO REFACTOR
	function subclasses_list($ip) {
				
		$list = array($ip);
		$array = explode('.', $ip);
		$size = count($array) - 1;
		while ($size > 1)  {
			$new_class = $array[0];
			for ($i=1; $i < $size; $i++) {
				$new_class .= '.' . $array[$i];
			}
			$list[]=$new_class;
			$size--;
		}
		return $list;
	}
	
	//TODO REFACTOR
	function subdomains_list($domain_path, $first_level = false) {
		$paths = array();
		// search for the first part of the path
		if(preg_match('/^[^\/]+\/+([^\/\?]+)[\/\?]*/', $domain_path, $match) > 0) {
			$paths[0] = $match[1];
			// search for the second part of the path
			if($paths[0] && preg_match('/^[^\/]+\/+[^\/\?]+\/+([^\/\?]+)[\/\?]*/', $domain_path, $match) > 0) {
				$paths[1] = $paths[0].'/'.$match[1];
			}
		}

		$domain = preg_replace('/\/.*$/', '', $domain_path);
		$list = array($domain);
		foreach ($paths as $path) {
			$list[]=$domain.'/'.$path;
			$list[]=$domain.'/'.$path.'/';
		}
		
		$array = explode('.', $domain);
		
		$domain_limit=($first_level)?  count($array): count($array) - 1;

		for($i=1; $i < $domain_limit; $i++) {
			$sub = array_slice($array, $i);
			$sub = implode('.', $sub);
			$list[]=$sub;
			if ($i < $domain_limit ) { // Add path only if there is at least a second level, avoid tk/path
				foreach ($paths as $path) {
					$list[]=$sub.'/'.$path;
					$list[]=$sub.'/'.$path.'/';
				}
			}
		}
		return $list;
	}	
}